package us.versus.them.triangle_mountain;

import opengl.GL;

class Pt3 {
	public var x : Float;
	public var y : Float;
	public var z : Float;

	static var count = prepare();
	var id : Int;

	var n:Int;

	public function new( ?x : Float, ?y : Float, ?z : Float ) {
		if ( null == x ) x = 0;
		if ( null == y ) y = 0;
		if ( null == z ) z = 0;
		this.set( x, y, z );
		this.id = ( count++ );
	}

	public function set( ?x : Float, ?y : Float, ?z : Float ) {
		this.x = x;
		this.y = y;
		this.z = z;
		this.n = 0;
	}

	public function toString() { 
		return "" + id;
	}

	public function print() {
		return this.x + ',' + this.y + ',' + this.z;
	}

	public function vertex() {
		GL.vertex3( x, y, z );
	}

	public function color() {
		GL.color3( x, y, z );
	}

	public function normal() {
		GL.normal3( x, y, z );
	}

	public function length2() {
		return this.dot( this );
	}

	public function add( that:Pt3 ) {
		this.x += that.x;
		this.y += that.y;
		this.z += that.z;
		n++;
	}

	public function average() {
		this.x /= n;
		this.y /= n;
		this.z /= n;
	}

	public function dot( that : Pt3 ) {
		return ( 0
			+ this.x * that.x
			+ this.y * that.y
			+ this.z * that.z
		);
	}

	public inline function cross( v1:Pt3, v2:Pt3 ) {
		this.x = ( v1.y * v2.z - v1.z * v2.y );
		this.y = ( v1.z * v2.x - v1.x * v2.z );
		this.z = ( v1.x * v2.y - v1.y * v2.x );
		return this;
	}

	public function normalize() {
		var l2 = this.dot( this );
		if ( 0 != l2 ) {
			l2 = invSqrt( l2 );
			this.x *= l2;
			this.y *= l2;
			this.z *= l2;
		}
	}

	// http://www.ncannasse.fr/blog/fast_inverse_square_root
	public static function prepare() {
#if flash
	    var b = new flash.utils.ByteArray();
	    b.length = 1024;
	    flash.Memory.select( b );
#end
		return 0;
	}

	public static function invSqrt( x : Float ) : Float {
#if flash
		var half = 0.5 * x;
		flash.Memory.setFloat(0,x);
		var i = flash.Memory.getI32(0);
		i = 0x5f3759df - (i>>1);
		flash.Memory.setI32(0,i);
		x = flash.Memory.getFloat(0);
		x = x * (1.5 - half*x*x);
#else
		x = 1 / Math.sqrt( x );
#end
		return x;
	}


}
